home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / viewers / pvquan16 / vga / vga400.c < prev   
C/C++ Source or Header  |  1992-11-30  |  4KB  |  130 lines

  1. /************************************************************************
  2.  *                                                                      *
  3.  *                  Copyright (c) 1991, Frank van der Hulst             *
  4.  *                          All Rights Reserved                         *
  5.  *                                                                      *
  6.  * Authors:                                                             *
  7.  *          FvdH - Frank van der Hulst (Wellington, NZ)                     *
  8.  *                                                                      *
  9.  * Versions:                                                            *
  10.  *      V1.1 910626 FvdH - QUANT released for DBW_RENDER                *
  11.  *      V1.2 911021 FvdH - QUANT released for PoV Ray                   *
  12.  *                                                                      *
  13.  ************************************************************************/
  14. /*
  15.  
  16. VGA 320 * 400 * 256 mode display module.
  17.  
  18. This file contains routines to display images in 320*400 mode by modifying
  19. the VGA registers, as outlined in Programmer's Journal V7.1 (Jan/Feb '89)
  20. article, pages 18-30, by Michael Abrash.
  21.  
  22. The advantage of 320 * 400, is that it gives two separate video pages, which
  23. can be displayed on the screen independently. These contain two views of a
  24. scene, taken from slightly different viewpoints. These are displayed
  25. alternately on the screen, in sync with a pair of "chopper glasses", to give
  26. a 3D effect.
  27. */
  28.  
  29. #include <dos.h>
  30. #include <mem.h>
  31.  
  32. #include "vga.h"
  33.  
  34. static unsigned int act_page = 0;        /* Current page being written to */
  35.  
  36. #define VGA_SEGMENT        0xa000
  37. #define SC_INDEX           0x3c4
  38. #define GC_INDEX           0x3ce
  39. #define CRTC_INDEX         0x3d4
  40.  
  41. #define MAP_MASK           2
  42. #define MEMORY_MODE        4
  43. #define GRAPHICS_MODE      5
  44. #define MISCELLANEOUS      6
  45. #define MAX_SCAN_LINE      9
  46. #define START_ADDRESS_HIGH 0x0c
  47. #define UNDERLINE          0x14
  48. #define MODE_CONTROL       0x17
  49.  
  50. void putpixel_400(unsigned int x, unsigned int y, unsigned char colour)
  51. {
  52.     char far *addr;
  53.  
  54.     addr = MK_FP(VGA_SEGMENT, (x >> 2) + 320/4 * y + act_page);
  55.     outport(SC_INDEX, (0x100 << (x & 3)) | MAP_MASK);
  56.     *addr = colour;
  57. }
  58.  
  59. void set320x400mode(void)
  60. {
  61.     struct REGPACK regs;
  62.     unsigned char x;
  63.  
  64.     regs.r_ax = 0x13;                /* Set 320*200*256 graphics mode via BIOS */
  65.     intr(0x10, ®s);
  66.  
  67. /* Change CPU addressing of video memory to linear (not odd/even, chain, or
  68.     chain 4), to allow access to all 256K of display memory. Each byte will now
  69.     control one pixel, with 4 adjacent pixels at any given address, one pixel
  70.     per plane. */
  71.  
  72.     outportb(SC_INDEX, MEMORY_MODE);
  73.     x = inportb(SC_INDEX+1);
  74.     x &= 0xf7;                                    /* Turn off chain 4  */
  75.     x |= 4;                                        /* Turn off odd/even */
  76.     outportb(SC_INDEX+1, x);
  77.     outportb(GC_INDEX, GRAPHICS_MODE);
  78.     x = inportb(GC_INDEX+1);
  79.     x &= 0xef;                                    /* Turn off odd/even */
  80.     outportb(GC_INDEX+1, x);
  81.     outportb(GC_INDEX, MISCELLANEOUS);
  82.     x = inportb(GC_INDEX+1);
  83.     x &= 0xfd;                                    /* Turn off chain */
  84.     outportb(GC_INDEX+1, x);
  85.  
  86. /* Now clear the whole screen, since the mode 13h set only clears 64K. Do this
  87.     before switching CRTC out of mode 13h, so that we don't see grabage on the
  88.     screen. */
  89.  
  90.     outport(SC_INDEX, 0x0f00 | MAP_MASK);            /* Write to 4 planes at once */
  91.     setmem(MK_FP(VGA_SEGMENT, 0), 0xffff, 0);
  92.  
  93. /* Change mode to 320*400 by not scanning each line twice. */
  94.     outportb(CRTC_INDEX, MAX_SCAN_LINE);
  95.     x = inportb(CRTC_INDEX+1);
  96.     x &= 0xe0;                                /* Set maximum scan line to 0 */
  97.     outportb(CRTC_INDEX+1, x);
  98.  
  99. /* Change CRTC scanning from doubleword to byte mode, allowing the CRTC to
  100.     scan more than 64K */
  101.     outportb(CRTC_INDEX, UNDERLINE);
  102.     x = inportb(CRTC_INDEX+1);
  103.     x &= 0xbf;                    /* Turn off doubleword */
  104.     outportb(CRTC_INDEX+1, x);
  105.     outportb(CRTC_INDEX, MODE_CONTROL);
  106.     x = inportb(CRTC_INDEX+1);
  107.     x |= 0x40;                    /* Turn on the byte mode bit, so memory is linear */
  108.     outportb(CRTC_INDEX+1, x);
  109.     outport(CRTC_INDEX, 0 | START_ADDRESS_HIGH); /* Start on page 0 */
  110. }
  111.  
  112. void end320x400mode(void)
  113. {
  114.     struct REGPACK regs;
  115.  
  116.     regs.r_ax = 3;                /* Return to text mode */
  117.     intr(0x10, ®s);
  118. }
  119.  
  120. void setvis_400(int page)
  121. {
  122.     outport(CRTC_INDEX, (page << 15) | START_ADDRESS_HIGH);
  123. }
  124.  
  125. char far *setact_400(int page)
  126. {
  127.     act_page = page ? 0x8000 : 0;
  128.     return MK_FP(VGA_SEGMENT, act_page);
  129. }
  130.